package sim_moteur.element;

/**
 * Classe mère de tous les être vivants. Elle définit la vie et la position du
 * vivant. Le vivant possède également un attribut etat qui représente sa
 * perception de sa condition et une variable action qui représente l'action
 * qu'il est en train d'exécuter.
 * 
 * @author Martin Simoneau
 * 
 */
public abstract class Vivant extends Chose {

	public enum Etat {
		NOUVEAU, VIVANT, ANIMAL_FATIGUE, ANIMAL_EPUISE, ANIMAL_AFFAME, ANIMAL_FRINGALE, MORT, PLANTE_MATURE, PLANTE_VIEILLE
	}

	public enum Action {
		NOUVEAU, ANIMAL_MARCHE, ANIMAL_MANGE, ANIMAL_REPOSE, VEGETAL_REPRODUIRE, VEGETAL_NORMAL, MOURIR
	}

	protected float vie; // vivant si supérieur à 0
	protected Etat etat;
	protected Action action;

	public Vivant(String name, float vitalite) {
		super(name);
		vie = vitalite;
		etat = Etat.NOUVEAU;
		action = Action.NOUVEAU;
	}

	/**
	 * Exécute les actions du vivant pour le pas de temps reçu en paramètre.
	 * 
	 * @param step
	 *            le pas de temps en cours
	 * @return vrai si le vivant est toujours en vie à la fin du pas de temps.
	 */
	abstract public boolean vit(long step);

	@Override
	public boolean estVivant() {
		return vie > 0;
	}

	/**
	 * Retourne la vie restante du vivant
	 * 
	 * @return la vie
	 */
	public float getVie() {
		return vie;
	}

	/**
	 * Ajuste la vie du vivant. Si la vie est inférieure à 0 l'être est mort. Le
	 * niveau de vie influence le comportement de l'être vivant.
	 * 
	 * @param vie
	 *            le niveau de vie de l'être.
	 */
	public void setVie(float vie) {
		this.vie = vie;
	}

	/**
	 * Action à exécuter lorsque le vivant meurt.
	 */
	public void meurt() {
		vie = 0;
		etat = Etat.MORT;
		action = Action.MOURIR;
	}

	/**
	 * Transfert la vie d'un vivant à un autre. Principalement parce qu'il est
	 * mangé !
	 * 
	 * @param autreVivant
	 *            le mangeur
	 * @param vieTransferee
	 *            la quantité de vie transférée
	 * @return
	 */
	public boolean transfertVie(Vivant autreVivant, float vieTransferee) {

		float vieTransferable = Math.min(vieTransferee, this.vie);
		autreVivant.vie += vieTransferable;
		this.vie -= vieTransferee;

		// S'il ne reste plus de vie, il est mort
		if (this.vie < 0) {
			this.action = Action.MOURIR;
			this.etat = Etat.MORT;
		}

		return this.vie > 0;
	}

	public Etat getEtat() {
		return etat;
	}

	public Action getAction() {
		return action;
	}

	@Override
	public String toString() {
		return super.toString() + "vitalité:" + vie + "\n" + "État: " + etat
				+ "\nAction: " + action + "\n";
	}
}
